package com.quanxiaoha.weblog.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quanxiaoha.weblog.common.domain.entity.ScheduleTag;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleTagMapper;
import com.quanxiaoha.weblog.common.domain.query.CensusQuery;
import com.quanxiaoha.weblog.common.domain.vo.*;
import com.quanxiaoha.weblog.common.domain.entity.ScheduleRecord;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleRecordMapper;
import com.quanxiaoha.weblog.common.domain.query.RecordQuery;
import com.quanxiaoha.weblog.common.domain.query.ScheduleRecordQuery;
import com.quanxiaoha.weblog.common.enums.FeelingEnum;
import com.quanxiaoha.weblog.common.service.IScheduleRewardService;
import com.quanxiaoha.weblog.common.service.IScheduleSkillService;
import com.quanxiaoha.weblog.common.service.ScheduleCountService;
import com.quanxiaoha.weblog.common.service.ScheduleRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ScheduleRecordServiceImpl extends ServiceImpl<ScheduleRecordMapper, ScheduleRecord> implements ScheduleRecordService {

    @Autowired
    private ScheduleTagMapper tagMapper;

    @Autowired
    private ScheduleCountService countService;

    @Autowired
    @Lazy
    private IScheduleRewardService rewardService;

    @Autowired
    private IScheduleSkillService skillService;


    @Override
    public Page<ScheduleRecordVo> RecordList(RecordQuery recordQuery) {

        Page<ScheduleRecord> page = new Page<>();
        page.setCurrent(recordQuery.getCurrent());
        page.setSize(recordQuery.getSize());

        // 构建查询条件
        LambdaQueryWrapper<ScheduleRecord> wrapper = new LambdaQueryWrapper<>();

        String name = recordQuery.getScheduleName();
        LocalDateTime startDate = Objects.nonNull(recordQuery.getStartDate())
                ? recordQuery.getStartDate().atStartOfDay() : null;
        LocalDateTime endDate = Objects.nonNull(recordQuery.getEndDate())
                ? LocalDateTime.of(recordQuery.getEndDate(), LocalTime.MAX) : null;
        Integer tagId = recordQuery.getTagId();

        wrapper
                .like(StringUtils.isNotBlank(name), ScheduleRecord::getScheduleName, name.trim()) // like 模块查询
                .eq(Objects.nonNull(tagId), ScheduleRecord::getTagId, tagId)
                .ge(Objects.nonNull(startDate), ScheduleRecord::getCreateTime, startDate) // 大于等于 startDate
                .le(Objects.nonNull(endDate), ScheduleRecord::getCreateTime, endDate)  // 小于等于 endDate
                .orderByDesc(ScheduleRecord::getCreateTime); // 按创建时间倒叙


        Page<ScheduleRecord> res = this.page(page, wrapper);
        Page<ScheduleRecordVo> bos = new Page<>();
        bos.setTotal(res.getTotal());
        bos.setCurrent(res.getCurrent());
        bos.setSize(res.getSize());
        bos.setRecords(BeanUtil.copyToList(res.getRecords(), ScheduleRecordVo.class));
        return bos;
    }

    @Override
    public ScheduleRecordVo getRecord(Integer id) {

        ScheduleRecord byId = this.getById(id);
        ScheduleRecordVo bo = BeanUtil.copyProperties(byId, ScheduleRecordVo.class);
        return bo;
    }

    @Override
    public void insertRecord(ScheduleRecordQuery scheduleRecordQuery) {


        ScheduleRecord scheduleRecord = BeanUtil.copyProperties(scheduleRecordQuery, ScheduleRecord.class);
        LambdaQueryWrapper<ScheduleRecord> qw = new LambdaQueryWrapper<>();
        qw.orderByDesc(ScheduleRecord::getCreateTime)
                .last("LIMIT 1");
        ScheduleRecord one = this.getOne(qw);
        if (Objects.nonNull(one)) {
            scheduleRecord.setCreateTime(one.getEndTime());
            scheduleRecord.setPastId(one.getId());
        }

        //判断开始时间是否小于结束时间
        LocalDateTime endTime = LocalDateTime.now();
        if(one.getEndTime().toLocalTime().isBefore(endTime.toLocalTime())){
            scheduleRecord.setEndTime(endTime);
            this.save(scheduleRecord);
            //保存次数
            try {
                countService.saveCount(scheduleRecord);
            }catch (Exception e){
                e.printStackTrace();
            }
            //消费积分和连续工作
            consume(scheduleRecordQuery.getTagId(),one.getEndTime(),endTime);
        }else {
            scheduleRecord.setEndTime(one.getEndTime().with(LocalTime.MAX));
            ScheduleRecord newOne = BeanUtil.copyProperties(scheduleRecord, ScheduleRecord.class);
            this.save(scheduleRecord);
            //保存次数
            try {
                countService.saveCount(scheduleRecord);
            }catch (Exception e){
                e.printStackTrace();
            }
            //消费积分和连续工作
            consume(scheduleRecordQuery.getTagId(),scheduleRecord.getCreateTime(),scheduleRecord.getEndTime());
            newOne.setCreateTime(endTime.with(LocalTime.MIN));
            newOne.setPastId(scheduleRecord.getId());
            newOne.setEndTime(endTime);
            this.save(newOne);
            //保存次数
            try {
                countService.saveCount(newOne);
            }catch (Exception e){
                e.printStackTrace();
            }
            consume(scheduleRecordQuery.getTagId(),newOne.getCreateTime(),newOne.getEndTime());
        }

        //保存奖励
        try {
            if(scheduleRecordQuery.getTagId()==1
                ||scheduleRecordQuery.getTagId()==6
                ||scheduleRecordQuery.getTagId()==7
                ||scheduleRecordQuery.getTagId()==8){
                rewardService.saveReward(scheduleRecordQuery.getReward(),scheduleRecordQuery.getTagId());
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        //完成任务
        try {
            if(scheduleRecordQuery.getTagId()==1&&scheduleRecordQuery.getIsTask()){
                skillService.checkStage(scheduleRecordQuery.getStageId());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void consume(int tagId, LocalDateTime startTime, LocalDateTime endTime){

        //消费积分和连续工作
        try {
            Duration duration = Duration.between(startTime, endTime);
            int minutes = (int)duration.toMinutes(); // 直接获取总分钟差[3,7](@ref)
            //连续工作
            rewardService.continuousWork(tagId,minutes);
            //消费积分
            rewardService.autoConsume(tagId,minutes);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void updateRecord(ScheduleRecordQuery scheduleRecordQuery) {

        ScheduleRecord scheduleRecord = BeanUtil.copyProperties(scheduleRecordQuery, ScheduleRecord.class);
        scheduleRecord.setUpdateTime(LocalDateTime.now());
        this.updateById(scheduleRecord);
    }

    @Override
    public void deleteRecord(Integer id) {

        this.removeById(id);
    }

    @Override
    public List<ScheduleTagVo> tagList() {

        List<ScheduleTag> scheduleTags = tagMapper.selectList(null);
        List<ScheduleTagVo> scheduleTagVos = BeanUtil.copyToList(scheduleTags, ScheduleTagVo.class);

        return scheduleTagVos;
    }

    @Override
    public List<CensusVo> census(CensusQuery query) {

        List<ScheduleTag> scheduleTags = tagMapper.selectList(null);
        if(Objects.isNull(scheduleTags))return null;
        Map<Integer, String> tagMap = scheduleTags.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getName()));
        List<ScheduleRecord> list = getListByDate(query);
        List<CensusVo> res = list.stream().map(x -> {
            Duration duration = Duration.between(x.getCreateTime(), x.getEndTime());
            long minutes = duration.toMinutes(); // 直接获取总分钟差[3,7](@ref)
            CensusVo censusVo = new CensusVo();
            censusVo.setName(tagMap.get(x.getTagId()));
            censusVo.setValue(minutes);
            return censusVo;
        }).collect(Collectors.toList());
        List<CensusVo> censusVos = mergeActivities(res);
        // 按年龄降序
        Collections.sort(censusVos, (p1, p2) -> Math.toIntExact(p2.getValue() - p1.getValue()));
        Map<String, List<ScheduleRecordVo>> stringListMap = censusMap(query);
        for (CensusVo censusVo : censusVos) {
                censusVo.setSchedules(stringListMap.get(censusVo.getName()));
        }
        return censusVos;
    }

    public Map<String, List<ScheduleRecordVo>>  censusMap(CensusQuery query) {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime inputDateTime = LocalDateTime.parse(query.getDayTime(), formatter);

        // 获取当天0点
        LocalDateTime startOfDay = inputDateTime.with(LocalTime.MIN); // 等价于00:00:00

        // 获取当天24点（精确至纳秒级最后一刻）
        LocalDateTime endOfDay = inputDateTime.with(LocalTime.MAX); // 23:59:59.999999999

        List<ScheduleRecordVo> vos =  baseMapper.censusList(startOfDay.toString(),endOfDay.toString(),null);
        Map<String, List<ScheduleRecordVo>> map = vos.stream().collect(Collectors.groupingBy(
                ScheduleRecordVo::getTagName,
                Collectors.toList()
        ));
        return map;
    }
    @Override
    public List<CensusVo> censusByFeeling(CensusQuery query) {

        List<ScheduleTag> scheduleTags = tagMapper.selectList(null);
        if(Objects.isNull(scheduleTags))return null;
        Map<Integer, String> tagMap = scheduleTags.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getName()));
        List<ScheduleRecord> list = this.list();
        List<CensusVo> res = list.stream().map(x -> {
            Duration duration = Duration.between(x.getCreateTime(), x.getEndTime());
            long minutes = duration.toMinutes(); // 直接获取总分钟差[3,7](@ref)
            CensusVo censusVo = new CensusVo();
            censusVo.setName(tagMap.get(x.getTagId()));
            censusVo.setValue(minutes/60);
            return censusVo;
        }).collect(Collectors.toList());
        List<CensusVo> censusVos = mergeActivities(res);
        return censusVos;
    }

    @Override
    public List<ReverseVo> reverseList(RecordQuery recordQuery) {

        LocalDateTime startDate = Objects.nonNull(recordQuery.getStartDate())
                ? recordQuery.getStartDate().atStartOfDay() : null;
        LocalDateTime endDate = Objects.nonNull(recordQuery.getEndDate())
                ? LocalDateTime.of(recordQuery.getEndDate(), LocalTime.MAX) : null;

        List<ScheduleRecordVo> vos = baseMapper.censusList(startDate.toString(), endDate.toString(), recordQuery.getScheduleName());
        List<ReverseVo> res = vos.stream().map(x -> {
            ReverseVo reverseVo = BeanUtil.copyProperties(x, ReverseVo.class);
            reverseVo.setCreateTime(x.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
            reverseVo.setEndTime(x.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
            reverseVo.setDate(x.getCreateTime().toLocalDate().toString());
            return reverseVo;
        }).collect(Collectors.toList());

        return res;
    }

    @Override
    public void calculateTask(Integer tagId) {

        //计算当日各个类别的时间
        LocalDateTime now = LocalDateTime.now();
        // 获取当天0点
        LocalDateTime startOfDay = now.with(LocalTime.MIN); // 等价于00:00:00

        // 获取当天24点（精确至纳秒级最后一刻）
        LocalDateTime endOfDay = now.with(LocalTime.MAX); // 23:59:59.999999999

        LambdaQueryWrapper<ScheduleRecord> qw = new LambdaQueryWrapper<>();
        qw.ge(ScheduleRecord::getCreateTime, startOfDay)  // create_time > startTime
                .lt(ScheduleRecord::getCreateTime, endOfDay);
        qw.eq(ScheduleRecord::getTagId, tagId);
        List<ScheduleRecord> list = this.list(qw);
        List<CensusVo> res = list.stream().map(x -> {
            Duration duration = Duration.between(x.getCreateTime(), x.getEndTime());
            long minutes = duration.toMinutes(); // 直接获取总分钟差[3,7](@ref)
            CensusVo censusVo = new CensusVo();
            censusVo.setName(x.getTagId().toString());
            censusVo.setValue(minutes);
            return censusVo;
        }).collect(Collectors.toList());
        List<CensusVo> censusVos = mergeActivities(res);
        censusVos.forEach(x -> {
           switch (x.getName()){
               case "1":{
                   if(x.getValue()>600){
                       rewardService.autoReward(60);
                       log.info("学习工作超过10小时，奖励60分钟");
                   }else if(x.getValue()>540){
                       rewardService.autoReward(50);
                       log.info("学习工作超过9小时，奖励50分钟");
                   }else if(x.getValue()>480){
                       rewardService.autoReward(40);
                       log.info("学习工作超过8小时，奖励40分钟");
                   }else if(x.getValue()>420){
                       rewardService.autoReward(30);
                       log.info("学习工作超过7小时，奖励30分钟");
                   }else if(x.getValue()>360){
                       rewardService.autoReward(20);
                       log.info("学习工作超过6小时，奖励20分钟");
                   }
                   break;
               }
               case "2":{
                   if(x.getValue()<120){
                       rewardService.autoReward(40);
                       log.info("浪费时间小于2小时，奖励40分钟");
                   }else if(x.getValue()<240){
                       rewardService.autoReward(20);
                       log.info("浪费时间小于4小时，奖励20分钟");
                   }
                   break;
               }
               case "3":{
                   if(x.getValue()>480){
                       rewardService.autoReward(40);
                       log.info("睡觉超过8小时，奖励40分钟");
                   }else if(x.getValue()>420){
                       rewardService.autoReward(30);
                       log.info("睡觉超过7小时，奖励30分钟");
                   }else if(x.getValue()>360){
                       rewardService.autoReward(20);
                       log.info("睡觉超过6小时，奖励20分钟");
                   }
                   break;
               }
               default:{
//                   System.out.println(x.getValue());
                   break;
               }
           }
        });
    }


    List<ScheduleRecord> getListByDate(CensusQuery query) {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime inputDateTime = LocalDateTime.parse(query.getDayTime(), formatter);

        // 获取当天0点
        LocalDateTime startOfDay = inputDateTime.with(LocalTime.MIN); // 等价于00:00:00

        // 获取当天24点（精确至纳秒级最后一刻）
        LocalDateTime endOfDay = inputDateTime.with(LocalTime.MAX); // 23:59:59.999999999

        LambdaQueryWrapper<ScheduleRecord> qw = new LambdaQueryWrapper<>();
        qw.ge(ScheduleRecord::getCreateTime, startOfDay)  // create_time > startTime
                .lt(ScheduleRecord::getCreateTime, endOfDay);
        List<ScheduleRecord> list = this.list(qw);

        return list;
    }

    // 假设原始对象为Activity类（包含name和value属性）
    public List<CensusVo> mergeActivities(List<CensusVo> list) {
        return list.stream()
                // 核心逻辑：按name分组，对value求和
                .collect(Collectors.toMap(
                        CensusVo::getName,  // 以name作为键
                        activity -> activity,  // 保留对象本身
                        (oldActivity, newActivity) -> {  // 合并规则：累加value
                            oldActivity.setValue(oldActivity.getValue() + newActivity.getValue());
                            return oldActivity;
                        }
                ))
                .values().stream()  // 提取去重后的对象集合
                .collect(Collectors.toList());
    }

}
